#pragma once
#include <iostream>
#include <memory>

#include <poll.h>

#include "Socket.hpp"
#include "Log.hpp"

const static int fd_size = 10;
const static int pollfd_size = 20;
const static int timeout = 1000;
class Poll
{
private:
public:
    Poll(uint16_t port)
        : _socket_server(new TCP_Server_Socket(port))
        , _nfds(pollfd_size)
        , _timeout(timeout)
    {
        // 初始化pollfd数组
        InitFds(_fds, pollfd_size);

        _socket_server->ServerInit();
        Add_fds(_socket_server->GetListenfd()); // 将listen_fd放入fd_arr中
    }
    ~Poll()
    {
        delete[] _fds;
    }
    // poll负责等
    void Loop()
    {
        while (true)
        {
            PrintDebug();
            int ret = poll(_fds, _nfds, _timeout);
            // 等成功了，有就绪的fd
            if (ret > 0)
            {
                Handler();
            }
            // 在timeout时间到了，没有就绪的fd
            else if (ret == 0)
            {
                std::cout << "没有fd就绪" << std::endl;
            }
            // poll error
            else
            {
                _log.LogMessage(ClassFile, Error, "select error, strerror : %s\n", strerror(errno));
                return;
            }
        }
    }

    // poll等成功了，执行的方法
    void Handler()
    {
        for(int i = 0; i < _nfds; ++i)
        {
            if(_fds[i].fd == -1) continue; // 无效的fd
            // 有效fd，看哪些事件就绪了
            if(_fds[i].revents & POLLIN) // 表明该事件就绪
            {
                // accept条件就绪
                if(_fds[i].fd == _socket_server->GetListenfd())
                {
                    _socket_server->Accept();
                    Add_fds(_socket_server->Getfd());
                }
                // recv 条件就绪
                else
                {
                    // 读取失败 / 读到末尾（对端关闭）
                    if(!_socket_server->Recv(_fds[i].fd))
                    {
                        Delete_fds(_fds[i].fd);
                    }
                }
            }

        }
    }

private:
    // 用于将新fd添加到fds 中管理
    void Add_fds(int fd)
    {
        int i = 0;
        for( ;i < _nfds; ++i)
        {
            if(_fds[i].fd == -1)
            {
                _fds[i].fd = fd;
                _fds[i].events = POLLIN;
                break;
            }
        }
        if(i == _nfds)
        {
            _log.LogMessage(ClassFile, Info, "pollfd的空间满了, 已自动扩容\n");
            GetMoreSpace();
        }
    }
    // 用于删除没用的fd
    void Delete_fds(int fd)
    {
        for(int i = 0; i < _nfds; ++i)
        {
            if(_fds[i].fd == fd)
            {
                _fds[i].fd = -1;
                _fds[i].events = 0;
                _fds[i].revents = 0;
                close(fd);
                break;
            }
        }
    }

    void PrintDebug()
    {
        std::cout << "当前的fd有:" << std::endl;
        for(int i = 0; i < _nfds; ++i)
        {
            if(_fds[i].fd == -1) 
                continue;
            std::cout << _fds[i].fd << " ";
        }
        std::cout << std::endl;
    }
    // 扩容
    void GetMoreSpace()
    {
        pollfd *newfds = nullptr;
        InitFds(newfds, _nfds * 2);
        for(int i = 0; i < _nfds; ++i)
        {
            newfds[i].fd = _fds[i].fd;
            newfds[i].events = _fds[i].events;
            newfds[i].revents = _fds[i].revents;
        }
        delete[] _fds;
        _fds = newfds;
        _nfds = _nfds * 2;
    }   

    void InitFds(pollfd* &fds, int size)
    {
        fds = new pollfd[size];
        for(int i = 0; i < size; ++i)
        {
            fds[i].fd = -1;
            fds[i].events = 0;
            fds[i].revents = 0;
        }
    }

private:
    std::unique_ptr<Socket> _socket_server;
    nfds_t _nfds;  // pollfd结构体的个数
    pollfd *_fds;  // 用户与内核传递fd的事件是否关心，是否就绪
    int _timeout;  // poll的等待模式 ： 阻塞 、 非阻塞 、 阻塞+非阻塞
};